<template>
  <div class="wrap">
    <blocklayout :rightStyle="{ padding: '4px' }">
      <template #left>
        <MonacoDditor v-model="json" language="json" />
      </template>

      <template #menu>
        <CommonMenu :menuConfig="menuConfig" v-model="JsonPrettyAttrs" />

        <div class="btns">
          <el-button type="primary" size="small" :disabled="!selectedValue" @click="copySelectValue">
            复制选中的值
            <i class="iconfont icon-fuzhi"></i>
          </el-button>
        </div>
      </template>

      <template #right>
        <VueJsonPretty v-model:data="jsonData" v-bind="JsonPrettyAttrs" v-model:selectedValue="selectedValue" />
      </template>
    </blocklayout>
  </div>
</template>

<script lang="ts" setup>
import VueJsonPretty from "vue-json-pretty";
import "vue-json-pretty/lib/styles.css";
import { ref, reactive, watch } from "vue";
import pkg from "root/package.json";
import useCopy from "@/hook/useCopy";
import menuConfig from "./menuConfig";

// https://github.com/leezng/vue-json-pretty/blob/HEAD/README.zh_CN.md

type JsonPrettyAttrsProps = InstanceType<typeof VueJsonPretty>["$props"];

const JsonPrettyAttrs = reactive<Record<string, any>>({
  showLength: true,
  showLineNumber: true,
  showLine: true,
  showDoubleQuotes: true,
  showIcon: true,
  collapsedOnClickBrackets: true,
  editable: true,
  editableTrigger: "click",
  virtual: false,
  height: 400,
  itemHeight: 20,
  showSelectController: false,
  selectableType: "",
  selectOnClickNode: false,
  highlightSelectedNode: false,
  rootPath: "json",
  selectedValue: "string"
});

const json = ref(JSON.stringify(pkg, null, 2));
const jsonData = ref({});
// 当前选中的值
const selectedValue = ref<string | string[]>("");

// json 字符串编辑数据更新到 json
watch(
  json,
  val => {
    let res = null;
    try {
      res = JSON.parse(json.value);
      jsonData.value = res;
    } catch (error) {
      console.warn("json转换失败", json.value);
    }
  },
  { immediate: true }
);

// json 编辑数据更新到 json 字符串
watch(jsonData, val => {
  json.value = JSON.stringify(val);
});

// 开启数据选中时默认为单选且高亮
watch(
  () => JsonPrettyAttrs.showSelectController,
  val => {
    if (val) {
      JsonPrettyAttrs.selectableType = "single";
      JsonPrettyAttrs.highlightSelectedNode = true;
    } else {
      JsonPrettyAttrs.selectableType = "";
      selectedValue.value = "";
      JsonPrettyAttrs.highlightSelectedNode = false;
    }
  }
);

const copySelectValue = () => {
  let ret: string = "";
  // 源数据
  const origin = {
    [JsonPrettyAttrs.rootPath]: jsonData.value
  };
  const getKey = (key: string) => key.replace(`${JsonPrettyAttrs.rootPath}.`, "");

  if (typeof selectedValue.value === "string") {
    // 使用 eval 获取值
    const value = eval("origin." + selectedValue.value);
    ret = `${getKey(selectedValue.value)}: ${JSON.stringify(value, null, 2)}`;
  } else if (Array.isArray(selectedValue.value)) {
    selectedValue.value
      .filter(e => e)
      .map(e => {
        const value = JSON.stringify(eval("origin." + e), null, 2);
        // 将每次的值都拼到一起
        ret += `${getKey(e)}: ${value},\n`;
      });
  }

  useCopy(ret);
};
</script>

<style lang="scss" scoped>
$height: calc(100vh - 150px);
.wrap {
  max-height: $height;

  .btns {
    margin-top: 10px;
    text-align: center;
  }

  .menu {
    .menu-item {
      margin: 4px;
      .title {
        flex: 1;
        font-size: 12px;
      }
      .config {
        flex: 1;
        text-align: center;
      }
    }

    :deep(div.el-divider.el-divider--horizontal) {
      margin: 18px 0;
    }
  }
}
</style>
